package com.chen.base.config;

import com.chen.base.property.ThreadPool;
import com.chen.base.property.ThreadPoolProperties;
import com.chen.base.utils.SpringContextHolder;
import com.chen.base.utils.ThreadPoolUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.concurrent.Executor;

import static com.chen.root.constant.ThreadPoolCons.COMMON_THREAD_POOL;

/**
 * 线程池自动配置类
 * @author ferryman
 * @since 2022/1/28 15:59
 */
@Slf4j
@Configuration
@Import(SpringContextHolder.class)
public class ThreadPoolAutoConfig implements AsyncConfigurer {

	@Resource
	private ThreadPoolProperties poolProperties;

	@PostConstruct
	public void registerThreadPoolExecutor(){
		if (poolProperties.getList() == null){
			return;
		}
		for (ThreadPool pool : poolProperties.getList()) {
			// 排除公共线程池，并注册到spring容器中
			if (!COMMON_THREAD_POOL.equals(pool.getName())){
				ThreadPoolTaskExecutor executor = ThreadPoolUtil.build(pool);
				SpringContextHolder.registerBean(pool.getName(), executor);
			}
		}
	}

	/** 推荐：公共线程池配置 */
	@Bean(COMMON_THREAD_POOL)
	public Executor commonThreadPoolExecutor() {
		ThreadPool p = poolProperties.getThreadPool(COMMON_THREAD_POOL);
		if (p == null){
			// CPU 核心数
			int cpuCore = Runtime.getRuntime().availableProcessors();

			p = new ThreadPool();
			p.setName(COMMON_THREAD_POOL);
			p.setCorePoolSize(cpuCore * 2);
			p.setMaxPoolSize(cpuCore * 20);
			p.setQueueCapacity(cpuCore * 20);
			p.setKeepAliveSeconds(60);
			p.setRefuseStrategy(1);
		}
		log.info("初始化公共线程池: Name={}, CorePoolSize={}, MaxPoolSize={}, QueueCapacity={}, KeepAliveSeconds={}",
				p.getName(), p.getCorePoolSize(), p.getMaxPoolSize(), p.getQueueCapacity(), p.getKeepAliveSeconds());
		return ThreadPoolUtil.build(p);
	}

	/**
	 * 替换spring默认的线程池
	 */
	@Override
	public Executor getAsyncExecutor() {
		return SpringContextHolder.getBean(COMMON_THREAD_POOL);
	}
}
